import asyncio
import json
import os
import re
import sys
import websockets
from socket import gethostbyname
from client import Client

# 设置窗口信息
TITLE = "文件同步程序"
MOTD = "[INFO] 欢迎使用同步程序！"
CONFIG_FILE = os.getcwd() + "/config.json"
os.system("title " + TITLE)
os.system("color f0")
print("[INFO] 软件作者21Hertz, 联系QQ2021583736")
print(MOTD)

try:
    with open(CONFIG_FILE, "r") as f:
        config: dict = json.loads(f.read())
    # 将域名解析为ip地址连接更稳定
    host = gethostbyname(config["host"])
    port = config["port"]
    workdir = config["workdir"]
    ignore_list = config.get("ignore", [])
    os.chdir(workdir)
    print(f"[INFO] 当前工作目录: {os.getcwd()}")
    print(f"[INFO] 服务端的地址: ws://{host}:{port}")
except Exception as error:
    input(f"[INFO] 启动失败! 读取配置时发生错误:\n{error}")
    sys.exit()


# 生成获取信息的请求
def actionInfo():
    action_dict = {"action": "GetInfo"}
    return json.dumps(action_dict)


# 生成获取文件的请求
def actionFile(file_name):
    action_dict = {"action": "GetFile", "name": file_name}
    return json.dumps(action_dict)


# 保存配置文件
def save_config():
    config["ignore"] = ignore_list
    with open(CONFIG_FILE, "w") as fi:
        fi.write(json.dumps(config, indent=2, sort_keys=True))


# 用户确认或过滤
def user_confirm(download_files: list, remove_files: list):
    # 定义一个映射，简化代码
    LIST_MAPPING = [{"pattern": "\\d+", "list": download_files},
                    {"pattern": "-\\d+", "list": remove_files}]
    # 从过滤列表过滤部分文件
    for ignore_file in ignore_list:
        for mapping in LIST_MAPPING:
            if ignore_file in mapping["list"]:
                mapping["list"].remove(ignore_file)
    # 等待用户确认同步
    print("\n[INFO] 需下载的文件：")
    for idx, x in enumerate(download_files):
        print(f"    [{idx + 1}] {x}")
    print("[INFO] 需删除的文件：")
    for idy, y in enumerate(remove_files):
        print(f"    [-{idy + 1}] {y}")
    print("[INFO] 已过滤的文件：")
    for idz, z in enumerate(ignore_list):
        print(f"    [i{idz + 1}] {z}")
    print("\n[TIPS] 输入i新增过滤, d删除过滤")
    user_cmd = input("[INPU] 按下Enter开始同步...").upper()
    if user_cmd == "I":
        print("\n[INFO] 过滤的文件将不会下载或删除")
        print("[INFO] 输入需要过滤的文件对应序号")
        user_in = input("[INPU] 多项之间使用空格分开：")
        # 开始处理用户输入
        user_in_list = user_in.split(" ")
        for item in user_in_list:
            for mapping in LIST_MAPPING:
                reg = re.match(mapping["pattern"], item)
                if reg:
                    index = abs(int(reg.group())) - 1
                    if index in range(len(mapping["list"])):
                        ignore_list.append(mapping["list"][index])
                    break
        # 保存过滤列表并刷新
        save_config()
        return user_confirm(download_files, remove_files)
    elif user_cmd == "D":
        print("\n[INFO] 输入需要删除的过滤对应编号")
        print("[INFO] 删除后请重启程序以获取更新！")
        user_in = input("[INPU] 多项之间使用空格分开：")
        # 开始处理用户输入
        user_in_list = user_in.split(" ")
        tmp_list = []
        for item in user_in_list:
            reg = re.search("(?<=i)\\d+", item)
            if reg:
                index = int(reg.group()) - 1
                if index in range(len(ignore_list)):
                    tmp_list.append(ignore_list[index])
        for tmp in tmp_list:
            ignore_list.remove(tmp)
        # 保存过滤列表并刷新
        save_config()
        return user_confirm(download_files, remove_files)


async def hello():
    uri = f"ws://{host}:{port}"
    try:
        async with websockets.connect(uri) as websocket:
            # 获取服务器当前信息
            await websocket.send(actionInfo())
            info_dict = await websocket.recv()
            myClient = Client(json.loads(info_dict))
            download_files, remove_files = myClient.startDeal()
            # 用户确认
            user_confirm(download_files, remove_files)
            print("[INFO] 请耐心等待同步完成...")
            # 下载文件
            for down_file in download_files:
                print(f"[DOWN] 开始下载: {down_file}")
                try:
                    await websocket.send(actionFile(down_file))
                    # 分片下载文件
                    file_content = b""
                    while True:
                        receive = await websocket.recv()
                        if receive == "complete!":
                            break
                        file_content += receive
                    # 如果有内容，保存数据到本地
                    if file_content:
                        with open(down_file, "wb") as file:
                            file.write(file_content)
                except Exception as err:
                    print(f"[INFO] 文件下载失败: {err}")
            # 删除文件
            for remove_file in remove_files:
                os.remove(remove_file)
            input(f"[INPU] 同步已全部完成, 按下Enter退出")
    except ConnectionRefusedError as err:
        input(f"[ERROR] 服务端连接失败, 请检查配置后重启\n{err}")
    except Exception as err:
        input(f"[ERROR] 未知错误, 请向开发者反馈:\n{err}")


asyncio.run(hello())

# pyinstaller -F main.py -i "logo.ico"
